using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

using RNChessRulesEngine;
using RNChessBoardCommonTypes;

namespace RNChessBoardControl.DemoApp
{
    public partial class Form1 : Form
    {

        protected StringBuilder _moveList = new StringBuilder();
        protected PlayerTurn _lastTurnSide = PlayerTurn.White;
        protected int _moveNumber = 0;

        public Form1()
        {
            InitializeComponent();

            this.rnChessBoardControl1.PlayerMove += new RNChessBoard.PlayerMoveEventHandler(rnChessBoardControl1_PlayerMove);
            _moveNumber++;
        }

        /// <summary>
        /// Event handler: Fired when player makes a move.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void rnChessBoardControl1_PlayerMove(object sender, RNChessBoard.PlayerMoveEventArgs e)
        {
            // Move template
            // {from}-{to}/move result/movetype/{from}-{to}/move result/movetype
            PlayerMoveResult pmr = e.PlayerMoveEventResult;

            if (pmr.PlayerSide == PlayerTurn.White)
            {
                _moveList.Append("\"" + pmr.MoveFromSAN + "-" + pmr.MoveToSAN + "/" +
                    GetMoveResultStringAsSAN(pmr.PlayerMoveStatus) + "/" +
                    GetMoveTypeStringAsSAN(pmr.PlayerMoveType) + "/" + "...");
            }
            else
            {
                _moveList.Replace("...",
                   pmr.MoveFromSAN + "-" + pmr.MoveToSAN + "/" +
                   GetMoveResultStringAsSAN(pmr.PlayerMoveStatus) + "/" +
                   GetMoveTypeStringAsSAN(pmr.PlayerMoveType) + "\",\n");
                _moveNumber++;
            }

            _lastTurnSide = pmr.PlayerSide;
            this.rtxtMovesList.Text = _moveList.ToString();
            label1.Text = _moveNumber.ToString();
            ShowFEN();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            this.rnChessBoardControl1.ResetBoard();
            _moveList = new StringBuilder();
            this.rtxtMovesList.Text = "";
            _moveNumber = 1;
            label1.Text = _moveNumber.ToString();
            ShowFEN();
        }

        private void ShowFEN()
        {
            this.txtFEN.Text =
               this.rnChessBoardControl1.GetCurrentPositionAsFEN();
        }

        /// <summary>
        /// Returns string containing the SAN representation for a given <see cref="MoveResult"/>
        /// enum type.
        /// </summary>
        /// <param name="moveResult"></param>
        /// <returns></returns>
        /// <remarks>
        /// This method returns flags that correspond to the result codes in the
        /// test games arrays.
        /// </remarks>
        private string GetMoveResultStringAsSAN(MoveResult moveResult)
        {
            if (moveResult == MoveResult.CHECK)
                return "+";
            else if (moveResult == MoveResult.ILLEGAL)
                return "!";
            else if (moveResult == MoveResult.LEGAL)
                return "";
            else if (moveResult == MoveResult.MATE)
                return "++";
            else
                return "";

        }

        /// <summary>
        /// Returns string containing the SAN representation for a given <see cref="MoveType"/>
        /// enum type.
        /// </summary>
        /// <param name="moveType"></param>
        /// <returns></returns>
        /// <remarks>
        /// This method returns flags that correspond to the move type codes in the
        /// test games arrays.
        /// </remarks>
        private string GetMoveTypeStringAsSAN(MoveType moveType)
        {
            if (moveType == MoveType.CAPTURE)
                return "x";
            else if (moveType == MoveType.KINGSIDE_CASTLE)
                return "O-O";
            else if (moveType == MoveType.QUEENSIDE_CASTLE)
                return "O-O-O";
            else if (moveType == MoveType.ENPASSANT)
                return "xep";
            else if (moveType == MoveType.ILLEGAL)
                return "!";
            else if (moveType == MoveType.PROMOTION)
                return "^";
            else if (moveType == MoveType.NONCAPTURE)
                return "nc";
            else
                return "";
        }

        private void btnRetractMove_Click(object sender, EventArgs e)
        {
            if (_moveNumber == 0)
                return;

            rnChessBoardControl1.RetractMove();

            if (_lastTurnSide == PlayerTurn.White)
            {
                _lastTurnSide = PlayerTurn.Black;

                if (_moveNumber == 0)
                {
                    this.rtxtMovesList.Text = "";
                    _moveList = new StringBuilder();
                    return;
                }

                int pos = _moveList.ToString().LastIndexOf("\n");
                _moveList.Remove(pos + 1, (_moveList.Length - (pos + 1)));
            }
            else
            {
                _lastTurnSide = PlayerTurn.White;
                string blackSAN = Regex.Replace(_moveList.ToString(), @"/[A-H][0-9]-[A-H][0-9]/.*/.*\n$", "/...");
                _moveList = new StringBuilder(blackSAN);
                _moveNumber--;
            }

            rtxtMovesList.Text = _moveList.ToString();
            label1.Text = _moveNumber.ToString();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
    }
}